﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace AnaViewer
{
    public class AnaPainter : IDisposable
    {


        private ItemSayingView<IItem> sayingView;
        ItemAuthorView authorView;
        ToolBarView toolBarView = null;

        Control owner = null;

        Bitmap yanduiLogo;
        Bitmap genLogo;
        Bitmap rssLogo;
        public AnaPainter(Control owner, Rectangle bounds )
        {
            yanduiLogo = Properties.Resources.yandui2;
            genLogo = Properties.Resources.Gen;
            rssLogo = Properties.Resources.rss;


            this.owner = owner;
            this.bounds = bounds;
            this.anaItemRect = bounds;
            InitializeSayingView();
            InitializeToolBarView();

            authorView = new ItemAuthorView();
            authorView.Invalidated += delegate(object sender, InvalidateEventArgs e) { Invalidate(); };
            sayingView.Invalidated += delegate(object sender, InvalidateEventArgs e) { Invalidate(); };
            toolBarView.Invalidated += delegate(object sender, InvalidateEventArgs e) { Invalidate(); };
            // 是否显示作者的头像
            authorView.VisibleChanged += delegate(object sender, EventArgs e) { SetRects(); Invalidate(); };


            SetRects();
        }

        Rectangle bounds;
        public Rectangle Bounds
        {
            get { return bounds; }
            set
            {
                if (bounds == value)
                    return;
                bounds = value;

                SetRects();

                if (scr == null || scr.Size != bounds.Size)
                {//重建 Screen 位图。
                    if (scr != null)
                    {
                        scr.Dispose();
                        scr = null;
                    }
                    scr = new Bitmap(bounds.Width, bounds.Height);
                }

                this.Invalidate(true);
            }
        }

        /// <summary>
        /// 设置各个部分的位置。
        /// </summary>
        void SetRects()
        {
            if (authorView.Visible)
            {
                //头像位置: (10, 24 + 10, 80, 80)
                authorView.Bounds = new Rectangle(0, 0, 80, 100);
                //语录位置: (10, 24 + 10, 400, 600)
                sayingView.Bounds = new Rectangle(80, 0, bounds.Width - 80, bounds.Height - 24 * 2);
                //工具栏位置: (0, 0, 400, 24)
                toolBarView.Bounds = new Rectangle(0, sayingView.Bounds.Bottom, bounds.Width, 24);//在sayingRect之下
            }
            else
            {
                //语录位置: (10, 24 + 10, 400, 600)
                sayingView.Bounds = new Rectangle(0, 0, bounds.Width, bounds.Height - 24 * 2);
                //工具栏位置: (0, 0, 400, 24)
                toolBarView.Bounds = new Rectangle(0, sayingView.Bounds.Bottom, bounds.Width, 24);//在sayingRect之下
            }

        }






        /// <summary>
        /// 初始化 rssDescriptionView 的显示属性。
        /// </summary>
        private void InitializeSayingView()
        {
            // 初始化 ItemDescriptionView 以显示 RssItem 的说明信息。
            // 该信息将出现在屏幕的右侧。
            sayingView = new ItemSayingView<IItem>();
        }


        #region InitializeToolBarView 初始化工具栏
        ImageList imageList;
        /// <summary>
        /// 初始化工具栏。
        /// </summary>
        void InitializeToolBarView()
        {
            toolBarView = new ToolBarView();
            toolBarView.SelectedIndexChanged += delegate(object sender, EventArgs e) { Invalidate(); };
            toolBarView.IsActiveChanged += delegate(object sender, EventArgs e) { Invalidate(); };
            toolBarView.VisibleChanged += delegate(object sender, EventArgs e) { Invalidate(); };

            imageList = new ImageList();
            imageList.ColorDepth = ColorDepth.Depth32Bit;
            imageList.ImageSize = new Size(14, 14);
            imageList.Images.AddStrip(Properties.Resources.icons);

            // "编辑", "评论[0]", "收藏[1]", "喜欢[22]", "不喜欢[0]", "举报[0]"
            AddButton("查看", 0, false);
            AddButton("编辑", 1, false);
            AddButton("评论", 2, false);
            AddButton("收藏", 3, false);
            //AddButton("喜欢", 4, false);
            //AddButton("不喜欢", 5, false);
            //AddButton("举报", 6, false);
            //AddButton("-", -1, false);
            //AddButton("头像", -1, false);
            AddButton("下篇", 9 + 4, true);
            AddButton("随机", 8 + 4, true);
            AddButton("上篇", 7 + 4, true);
            AddButton("-", -1, true);
        }

        ToolButton AddButton(string text, int imageIndex, bool rightAlign)
        {
            int startIndex = imageIndex * 3;

            ToolButton btn;
            if (startIndex >= 0 && startIndex + 2 < imageList.Images.Count)
                btn = new ToolButton(text, imageList.Images[startIndex + 1], imageList.Images[startIndex + 2], imageList.Images[startIndex]);
            else
                btn = new ToolButton(text, null, null, null);

            if (text.Trim() == "-")
                btn.IsSeparator = true;

            btn.RightToLeft = rightAlign;

            toolBarView.AddButton(btn);

            return btn;
        }
        #endregion


        public bool ToolBarVisible
        {
            get { return toolBarView.Visible; }
            set { toolBarView.Visible = value; }
        }
        public bool AuthorVisible
        {
            get { return authorView.Visible; }
            set { authorView.Visible = value; }
        }

        
        /// <summary>
        /// 对窗体操作模式（显示半透明背景和工具栏）
        /// </summary>
        bool oprMode = false;
        public bool OprMode
        {
            get { return oprMode; }
            set
            {
                if (oprMode == value)
                    return;
                
                oprMode = value;
                if (oprMode)
                {
                    toolBarView.Visible = true;
                }
                else
                {
                    toolBarView.Visible = false;
                }
                authorView.IsColor = (isHover || toolBarView.Visible);

                Invalidate();
            }
        }
        bool isHover = false;
        public bool IsHover
        {
            get { return isHover; }
            set
            {
                if (isHover == value)
                    return;
                isHover = value;


                authorView.IsColor = (isHover || toolBarView.Visible);

                Invalidate();
            }
        }



        private IItem displayItem;


        public IItem DisplayItem
        {
            get { return displayItem; }
            set
            {
                displayItem = value;

                sayingView.DisplayItem =displayItem;
                authorView.DisplayItem = displayItem;

                if (displayItem == null)
                {
                    toolBarView.LogoImage = genLogo;
                }
                else if (displayItem.GetType() == typeof(AnaItem))
                {
                    toolBarView.LogoImage = yanduiLogo;
                }
                else if (displayItem.GetType() == typeof(RssItem))
                {
                    toolBarView.LogoImage = rssLogo;
                }
                else
                {
                    toolBarView.LogoImage = genLogo;
                }
                

                this.Invalidate();
            }
        }







        private int lineWidth = 2;
        private Color lineColor1 = Color.White;
        public Color LineColor1
        {
            get { return lineColor1; }
            set { lineColor1 = value; this.Invalidate(); }
        }
        private Color lineColor2 = Color.FromArgb(128, Color.White);
        public Color LineColor2
        {
            get { return lineColor2; }
            set { lineColor2 = value; this.Invalidate(); }
        }
        public int LineWidth
        {
            get { return lineWidth; }
            set { lineWidth = value; this.Invalidate(); }
        }

        public Color anaBackColor = Color.FromArgb(100, Color.White);
        /// <summary>
        /// 半透明背景色。
        /// </summary>
        public Color AnaBackColor
        {
            get { return anaBackColor; }
            set { anaBackColor = value; this.Invalidate(); }
        }

        Font loading_Font = new Font("黑体", 18.0F);
        Color loading_BackColor = Color.White;
        Color loading_HoverBackColor = Color.Gold;
        int loading_BorderWidth = 2;
        float loading_Flatness = 0.1F;
        Color loading_ForeColor = Color.Black;


        /// <summary>
        /// 整个窗体的图片。
        /// </summary>
        Bitmap scr;

        public Bitmap ScreenBitmap
        {
            get { return scr; }
        }

        Color backColor = Color.Transparent;
        public void Paint(PaintEventArgs e)
        {
            if (scr == null || isInvalid)
            {//需要重绘图片。
                if (scr == null)
                    scr = new Bitmap(bounds.Width, bounds.Height);

                using (Graphics g = Graphics.FromImage(scr))
                {
                    g.Clear(backColor);
                    OnPaint(new PaintEventArgs(g, new Rectangle(0, 0, scr.Width, scr.Height)));
                }

                isInvalid = false;
            }
            //图片有效
            e.Graphics.DrawImageUnscaledAndClipped(scr,new Rectangle(e.ClipRectangle.Location, bounds.Size));
        }
        /// <summary>
        /// 重绘 Screen 图片。
        /// </summary>
        /// <param name="toolBarVisible"></param>
        protected virtual void OnPaint(PaintEventArgs e)
        {
            FreshScreenBmp();
        }
        public void RefreshUI()
        {
            if (isInvalid)
                FreshScreenBmp();
            isInvalid = false;
        }
        void FreshScreenBmp()
        {
            if (scr == null)
                scr = new Bitmap(bounds.Width, bounds.Height);
            using (Graphics g = Graphics.FromImage(scr))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.High;
                g.Clear(Color.Transparent);

                if (displayItem == null)
                {//不可见
                    Size size = new Size(scr.Width, 100);
                    Rectangle rect = new Rectangle((scr.Width - size.Width) / 2, 0, size.Width, size.Height);
                    PaintLoading(new PaintEventArgs(g, rect));
                }
                else
                {
                    Rectangle rect = new Rectangle(0, 0, scr.Width, scr.Height);
                    PaintAna(new PaintEventArgs(g, rect));
                }
            }
        }
        Rectangle anaItemRect;
        /// <summary>
        /// 绘制后，实际的区域（除去透明的部分）
        /// </summary>
        public Rectangle RealRect
        {
            get { return anaItemRect; }
        }
        /// <summary>
        /// 绘制 Ana 视图（包括头像、语录、工具栏）
        /// </summary>
        /// <param name="paintEventArgs"></param>
        private void PaintAna(PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            //绘制 Saying 面板
            sayingView.Paint(e);

            //Saying 面板上真正绘制了字体的区域
            int sayingBottom = (int)(sayingView.RealRect.Height + (sayingView.RealRect.Y - sayingView.Bounds.Y) * 2);
            int wholeBottom = Math.Max(sayingBottom, authorView.Bounds.Bottom);
            //实际的大小
            anaItemRect = new Rectangle(0, 0, bounds.Width, wholeBottom);

            if (isHover || toolBarView.Visible)
            {//绘制 Saying 半透明背景
                using (Brush brush = new SolidBrush(anaBackColor))
                using (GraphicsPath path = Common.GetPath(anaItemRect, 6))
                {
                    //g.FillRectangle(brush, realSayingRect);
                    g.FillPath(brush, path);
                }
            }
            //绘制 Saying 面板
            sayingView.Paint(e);

            if (authorView.Visible)
            {//头像可见，则绘制头像和分隔竖线
                authorView.Paint(e);

                //绘制渐变的分隔竖线
                g.SmoothingMode = SmoothingMode.Default;
                g.InterpolationMode = InterpolationMode.Default;
                //分隔线位置
                Rectangle lineRect = new Rectangle(authorView.Bounds.Right, 5, lineWidth, authorView.Bounds.Height - 5 * 2);
                //上半部分
                Rectangle lineRect1 = new Rectangle(lineRect.X, lineRect.Y, lineRect.Width, lineRect.Height / 2);
                //下半部分
                Rectangle lineRect2 = new Rectangle(lineRect.X, lineRect1.Bottom - 1, lineRect.Width, wholeBottom - lineRect1.Bottom);//lineRect.Height/2);
                using (Brush brush = new LinearGradientBrush(lineRect1, lineColor2, lineColor1, LinearGradientMode.Vertical))
                    g.FillRectangle(brush, lineRect1);
                using (Brush brush = new LinearGradientBrush(lineRect2, lineColor1, lineColor2, LinearGradientMode.Vertical))
                    g.FillRectangle(brush, lineRect2);
            }

            //------------- 因为 ToolBar 要相对于 Saying 的位置进行变化，所以应该后绘制
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.High;

            //根据正文的大小调整工具条的位置。
            toolBarView.Y = anaItemRect.Bottom + 5;


            //绘制 工具栏
            if (toolBarView.Visible)
                toolBarView.Paint(e);

#if DEBUG_SHOWBORDER
        g.DrawRectangle(Pens.Green, authorView.Bounds);
        g.DrawRectangle(Pens.Yellow, sayingView.Bounds);
        g.DrawRectangle(Pens.Red, toolBarView.Bounds);
#endif
        }

        /// <summary>
        /// 绘制“加载中”提示。
        /// </summary>
        /// <param name="e"></param>
        void PaintLoading(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle rect = e.ClipRectangle;


            if (isHover || toolBarView.Visible)
            {//绘制半透明背景
                using (Brush brush = new SolidBrush(Color.FromArgb(100, Color.White)))
                using (GraphicsPath path = Common.GetPath(rect, 6))
                {
                    //g.FillRectangle(brush, realSayingRect);
                    g.FillPath(brush, path);
                }
            }

            string text = "语录数据尚未准备好，请稍等...";
            Color color = loading_BackColor;
            if (isHover)
                color = loading_HoverBackColor;

            //绘制带描边的文本
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            using (StringFormat format = new StringFormat(StringFormatFlags.LineLimit))
            {
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
                using (GraphicsPath path = new GraphicsPath(FillMode.Alternate))
                {
                    path.AddString(text, loading_Font.FontFamily, (int)loading_Font.Style, loading_Font.Size, rect, format);
                    g.DrawPath(Pens.White, path);
                    g.FillPath(new SolidBrush(Color.Black), path);

                    if (loading_BorderWidth > 0)
                    {//描边
                        GraphicsPath pathBorder = path.Clone() as GraphicsPath;
                        pathBorder.Widen(new Pen(color, loading_BorderWidth), null, loading_Flatness);
                        g.FillPath(new SolidBrush(color), pathBorder);
                        g.DrawPath(new Pen(color, 1), pathBorder);
                    }
                    using (Brush textBrush = new SolidBrush(loading_ForeColor))//this.ForeColor))
                    {
                        //g.DrawPath(new Pen(this.ForeColor), path);
                        g.FillPath(textBrush, path);
                    }
                }
            }
        }

        /// <summary>
        /// 标识 界面 无效，需要更新。
        /// </summary>
        bool isInvalid = true;

        public bool IsInvalid
        {
            get { return isInvalid; }
        }

        /// <summary>
        /// 重写，标识 界面无效，在界面刷新定时器处理时是否刷新界面。
        /// </summary>
        public void Invalidate()
        {
            Invalidate(false);
        }
        public void Invalidate(bool invalidateChildren)
        {
            if (invalidateChildren)
            {
                sayingView.Invalidate();
                authorView.Invalidate();
                toolBarView.Invalidate();
            }
            if (!isInvalid)//第一次请求刷新
            {
                isInvalid = true;
                OnInvalidated(new InvalidateEventArgs(this.bounds));
            }
        }
        /// <summary>
        /// 在控件的显示需要重绘时发生。
        /// </summary>
        public event InvalidateEventHandler Invalidated;
        /// <summary>
        /// 引发 System.Windows.Forms.Control.Invalidated 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.InvalidateEventArgs。</param>
        protected virtual void OnInvalidated(InvalidateEventArgs e)
        {
            if (Invalidated != null)
                Invalidated(this, e);
        }

        #region IDisposable 成员

        public void Dispose()
        {
            sayingView.Dispose();
        }

        #endregion





        /// <summary>
        /// 使用指定的风格数据实例更新界面。
        /// </summary>
        /// <param name="theme"></param>
        public void UpdateTheme(ThemeData theme)
        {
            Color foreColor = theme.ForeColor;
            Color backColor = theme.BackColor;
            Color hoverColor = theme.HoverColor;
            Font authorFont = theme.AuthorFont;
            Font titleFont = theme.TitleFont;
            Font timeFont = theme.TimeFont;
            bool authorVisible = theme.AuthorVisible;
            HoverMode FaceEffect = theme.FaceEffect;

            // ----------- “载入进度条”样式 -----------
            this.loading_BackColor = backColor;
            //this.loading_BorderColor
            this.loading_BorderWidth = 4;
            this.loading_Flatness = 0.1F;
            this.loading_Font = titleFont;
            this.loading_ForeColor = foreColor;
            this.loading_HoverBackColor = hoverColor;


            this.AnaBackColor = Color.FromArgb(128, backColor);
            this.LineColor1 = backColor;
            this.lineColor2 = Color.FromArgb(96, backColor);
            this.LineWidth = 1;


            // ----------- 语录样式 | SayingView =Title_ -----------
            sayingView.BackColor = Color.Transparent;
            sayingView.BorderColor = backColor;
            sayingView.BorderWidth = 4;
            sayingView.Flatness = 0.1F;
            sayingView.Font = titleFont;
            sayingView.ForeColor = foreColor;
            sayingView.TimeFont = new Font(timeFont.FontFamily, timeFont.Size);

            // ----------- 头像样式 | AuthorView =Author_ -----------
            authorView.BackColor = Color.Transparent;
            authorView.BorderColor = backColor;
            authorView.BorderWidth = 2;
            authorView.Font = new Font(authorFont.FontFamily, authorFont.Size);
            authorView.ForeColor = foreColor;
            authorView.HoverBorderColor = hoverColor;
            authorView.HoverMode = FaceEffect;
            authorView.Visible = authorVisible;


            // ----------- 工具栏样式 | ToolBarView =Toolbar_* -----------
            toolBarView.ActiveBackColor = backColor;
            toolBarView.BackColor = Color.FromArgb(128, backColor);
            toolBarView.BorderColor = backColor;
            toolBarView.Font = new Font("宋体", 9.0F);
            toolBarView.ForeColor = foreColor;
            toolBarView.HoverBackColor = backColor;

            this.Invalidate();
        }











        public Cursor Cursor
        {
            get { return owner.Cursor; }
            set { owner.Cursor = value; }
        }

        public void OnMouseMove(MouseEventArgs e)
        {
            if (toolBarView.Bounds.Contains(e.Location))
            {
                toolBarView.SelectedItem = toolBarView.GetItemAt(e.Location);
                toolBarView.IsActive = false;
                if (toolBarView.SelectedItem == null)//没有选中项
                    this.Cursor = Cursors.Default;
                else//选中
                    this.Cursor = Cursors.Hand;
            }
            else
            {
                toolBarView.SelectedItem = null;
                if (authorView.RealRect.Contains(e.Location))
                {
                    authorView.IsActive = true;
                    this.Cursor = Cursors.Hand;
                }
                else
                {
                    authorView.IsActive = false;
                    this.Cursor = Cursors.Default;
                }
            }
        }
        public void OnMouseDown(MouseEventArgs e)
        {
            if (toolBarView.Bounds.Contains(e.Location))
            {
                toolBarView.SelectedItem = toolBarView.GetItemAt(e.Location);
                toolBarView.IsActive = true;
                this.Cursor = Cursors.Hand;
            }
            else
            {
                toolBarView.SelectedItem = null;
                this.Cursor = Cursors.Default;
            }
        }
        public void OnMouseUp(MouseEventArgs e)
        {
            if (toolBarView.Bounds.Contains(e.Location))
            {
                toolBarView.SelectedItem = toolBarView.GetItemAt(e.Location);
                toolBarView.IsActive = false;
                this.Cursor = Cursors.Hand;
            }
            else
            {
                toolBarView.SelectedItem = null;
                this.Cursor = Cursors.Default;
            }
        }

        public class ToolButtonEventArgs : EventArgs
        {
            ToolButton btn;
            public ToolButton Button
            {
                get{return btn;}
            }
            public ToolButtonEventArgs(ToolButton btn)
            {
                this.btn =btn;
            }
        }
        /// <summary>
        /// 语录区域 双击。
        /// </summary>
        public event EventHandler AnaDoubleClick;
        /// <summary>
        /// 工具栏 单击。
        /// </summary>
        public event EventHandler<ToolButtonEventArgs> ToolButtonClick;
        /// <summary>
        /// 头像 单击。
        /// </summary>
        public event EventHandler AuthorFaceClick;
        /// <summary>
        /// 工具栏LOGO 单击。
        /// </summary>
        public event EventHandler ToolBarLogoClick;


        public void OnMouseClick(MouseEventArgs e)
        {
            if (authorView.RealRect.Contains(e.Location))
            {
                if (AuthorFaceClick != null)
                    AuthorFaceClick(this, new EventArgs());
            }
            if (toolBarView.Bounds.Contains(e.Location))
            {
                if (toolBarView.HeadButton.Rect.Contains(e.Location))
                {//标题LOGO按钮
                    if (ToolBarLogoClick != null)
                        ToolBarLogoClick(this, new EventArgs());
                    return;
                }

                ToolButton btn = toolBarView.GetItemAt(e.Location);
                if (btn != null)
                {
                    if (ToolButtonClick != null)
                        ToolButtonClick(this, new ToolButtonEventArgs(btn));
                }
            }
        }
        public void OnMouseDoubleClick(MouseEventArgs e)
        {//双击工具栏和头像，无需动作
            //if (sayingView.RealRect.Contains(e.Location))
            if(anaItemRect.Contains(e.Location))
            {
                if (AnaDoubleClick != null)
                    AnaDoubleClick(this, new EventArgs());
            }
        }


    }
}
